﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization.Formatters.Binary;
using AdvancedTool;
using AdvancedTool.Standard;
using DiskToolSDK;
using static System.Console;
namespace DiskTool
{


    class ModReader : CoreBase
    {
        public override string Introduce => "模块读取设置";
        public override string Title => "修改模块读取位置";
        public override CoreType Type => CoreType.Setting;

        public override IUserInterface UserInterface => new DiskToolSDK.Basic.ConsoleUserInterface();

        public static string DllPath;
        public static string SaveFile;
        static void DllLoad(string path)
        {
            DllManager manager = DllManager.InitializeInstances(path);
            manager.Search(delegate (ClassExtends extends)
            {
                List<Type> types = new List<Type>();
                foreach (Type type in extends.ClassList)
                {
                    Type basetype = type.BaseType;
                    if (basetype != null)
                    {
                        if (basetype.Equals(typeof(IFileDoing)))
                        {
                            types.Add(type);
                        }
                    }
                }
                if (types.Count > 0)
                {
                    ModSelect.Types.Add(extends, types.ToArray());
                    return true;
                }
                else
                {
                    return false;
                }
            }
            );
        }
        public override void Function()
        {
            UserInterface.RequestOutPut($"功能插件读取地址：{DllPath}\n设置保存地址：{SaveFile}");
            int c = -1;
            while (c != 0)
            {
                UserInterface.RequestOutPut("1.修改 2.临时读取其他地址的插件  0.退出");
                c = UserInterface.RequestIntInput(0, 2);
                switch (c)
                {
                    case 1:
                        UserInterface.RequestOutPut("请输入地址");
                        string p = UserInterface.RequestTextInput();
                        try
                        {
                            object tmp = new DirectoryInfo(p);
                            DllPath = p;
                            UserInterface.RequestOutPut(Save() ? "保存设置成功" : "保存设置失败");
                            Starter(DllPath);
                            UserInterface.RequestOutPut("重读设置...");
                            ModSelect.OutPutClass();
                            UserInterface.RequestOutPut("重读完成");
                            UserInterface.RequestOutPut("修改成功");
                        }
                        catch
                        {
                            UserInterface.RequestOutPut("修改失败");
                        }

                        break;
                    case 2:
                        UserInterface.RequestOutPut("请输入插件所在文件夹路径");
                        string z = UserInterface.RequestTextInput();
                        DllLoad(z);
                        UserInterface.RequestOutPut("读取成功");
                        ModSelect.OutPutClass();
                        break;
                }
            }
        }
        public override void Pre_Do()
        {
            AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
            SaveFile = "DiskTool.setting";
            Starter("Mod");
        }
        void Starter(string dllpath)
        {
            DllPath = dllpath;
            ModSelect.Types = new Dictionary<ClassExtends, Type[]>();
            StartCheck(new DirectoryInfo(DllPath));
            DllLoad(DllPath);
        }
        void StartCheck(DirectoryInfo path)
        {
            if (!new FileInfo(SaveFile).Exists)
            {
                UserInterface.RequestOutPut(Save() ? "保存设置成功" : "保存设置失败");
            }
            else
            {
                UserInterface.RequestOutPut(Read() ? "读取设置成功" : "读取设置失败");
            }
            if (!path.Exists)
            {
                path.Create();
                DllPath = path.FullName;
            }
        }
        bool Save()
        {
            try
            {
                BinaryFormatter formatter = new BinaryFormatter();
                formatter.Serialize(new FileStream(SaveFile, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite), DllPath);
                return true;
            }
            catch (Exception ex)
            {
                UserInterface.RequestOutPut(ex.Message);
                return false;
            }

        }
        bool Read()
        {
            try
            {
                BinaryFormatter formatter = new BinaryFormatter();
                Object o = formatter.Deserialize(new FileStream(SaveFile, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite));
                DllPath = o.ToString();
                return true;
            }
            catch (Exception ex)
            {
                UserInterface.RequestOutPut(ex.Message);
                return false;
            }
        }
        Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
        {
            string p = new DirectoryInfo(DllPath).FullName + "/" + args.Name.Split(',')[0] + ".dll";
            return Assembly.LoadFile(p);
        }
    }

    class ModSelect : CoreBase
    {
        public static Dictionary<ClassExtends, Type[]> Types;
        static IUserInterface user = new DiskToolSDK.Basic.ConsoleUserInterface();
        public static void OutPutClass()
        {
            int index = 0;
            foreach (ClassExtends extends in Types.Keys)
            {
                user.RequestOutPut($"源文件：{extends.Source}");
                foreach (Type type in Types[extends])
                {
                    IFileDoing item = type.Assembly.CreateInstance(type.FullName) as IFileDoing;
                    CreatorAttribute attribute = type.GetCustomAttribute(typeof(DiskToolSDK.CreatorAttribute)) as CreatorAttribute;
                    string words = "";
                    if (attribute != null)
                    {
                        words = string.Format($"({index})类名：{type.Name},\t功能介绍：{item.About},\t操作对象类型:{item.SupportType.ToString()},\t作者信息：{attribute.Creator},\t是否可用：{attribute.IsFinish}");
                    }
                    else
                    {
                        words = string.Format($"({index})类名：{type.Name},\t功能介绍：{item.About},\t操作对象类型:{item.SupportType.ToString()}");
                    }
                    user.RequestOutPut(words);
                    index++;
                }
            }
        }
        IFileDoing[] AllInstanceList()
        {
            List<IFileDoing> re = new List<IFileDoing>();
            foreach (Type[] ts in Types.Values)
            {
                foreach (Type t in ts)
                {
                    re.Add((IFileDoing)(t.Assembly.CreateInstance(t.FullName)));
                }
            }
            return re.ToArray();
        }


        int LocationCheck(string z)
        {
            try
            {
                var fsi = new FileInfo(z);
                return fsi.Attributes == FileAttributes.Directory ? 2 : 1;
            }
            catch
            {
                return 0;
            }
        }
        void Feature()
        {
            var alltype = AllInstanceList();
            if (alltype.Length == 0)
            {
                UserInterface.RequestOutPut("无可用类");
            }
            else
            {
                int index = -1;
                while (true)
                {
                    UserInterface.RequestOutPut($"请选择功能(-1~{alltype.Length - 1})：");
                    OutPutClass();
                    index = UserInterface.RequestIntInput(-1, alltype.Length - 1);
                    if (index.ToString().Equals("-1"))
                    {
                        UserInterface.RequestOutPut("正在退出。按下任意键退出，取消退出请输入back(无视大小写)");
                        if (!UserInterface.RequestTextInput().ToUpper().Equals("BACK"))
                        {
                            break;
                        }
                        else
                        {
                            Feature();
                        }
                    }
                    try
                    {
                        IFileDoing doing = alltype[index];
                        Type t = doing.GetType();
                        CreatorAttribute att = t.GetCustomAttribute(typeof(CreatorAttribute)) as CreatorAttribute;
                        string name = t.Name;
                        if (att != null)
                        {
                            if (!att.IsFinish)
                            {
                                UserInterface.RequestOutPut("该功能不可用");
                                continue;
                            }
                        }
                        UserInterface.RequestOutPut($"已选择{name}");
                        UserInterface.RequestOutPut("输入需要处理的文件(夹)路径");
                        string p = UserInterface.RequestTextInput();
                        int lc = LocationCheck(p);
                        bool hasdo = false;
                        if (lc == 2 && doing.SupportType != ProcessingType.File)
                        {
                            FileFinder finder = new FileFinder(p, doing.FileExtends);
                            doing.Init();
                            finder.OnFileFound += doing.FileHandle;
                            finder.Search(doing.UseExtend);
                            doing.End();
                            hasdo = true;
                        }
                        if (lc == 1 && doing.SupportType != ProcessingType.Folder)
                        {
                            doing.Init();
                            doing.FileHandle(new FileInfo(p));
                            doing.End();
                            hasdo = true;
                        }
                        if (lc == 0)
                        {
                            UserInterface.RequestOutPut("错误路径");
                        }
                        if (!hasdo)
                        {
                            UserInterface.RequestOutPut("该功能不支持处理该文件/文件夹");
                        }

                    }
                    catch (Exception x)
                    {
                        UserInterface.RequestOutPut(x.Message);
                    }


                }

            }
        }
        public override CoreType Type => CoreType.Feature;

        public override string Introduce => "通过提供读取的模块进行选择";

        public override string Title => "功能选择";

        public override IUserInterface UserInterface => user;

        public override void Function()
        {
            Feature();
        }


    }

}
